﻿using System;
using System.Threading.Tasks;
using net.xBei.Models.json;

namespace net.xBei.WebApi.Helper;
/// <summary>
/// 使用<see cref="ResponseData{T}"/>作为返回值的方法链式调用
/// </summary>
public static class FlowHelper {
    /// <summary>
    /// 如果<paramref name="taskData"/>.Success == <see langword="true"/> 则执行<paramref name="action"/>并返回原始的<paramref name="taskData"/>，否则直接返回。
    /// 此方法不会改变数据
    /// </summary>
    /// <param name="taskData"></param>
    /// <param name="action"></param>
    /// <returns></returns>
    public static async Task<ResponseData> ThenAsync(this Task<ResponseData> taskData, Action<ResponseData> action) {
        var data = await taskData;
        if (data.Success) {
            action.Invoke(data);
        }
        return data;
    }
    /// <summary>
    /// 如果<paramref name="taskData"/>.Success == <see langword="true"/> 则执行<paramref name="action"/>并返回原始的<paramref name="taskData"/>，否则直接返回。
    /// 此方法不会改变数据
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="taskData"></param>
    /// <param name="action"></param>
    /// <returns></returns>
    public static async Task<ResponseData<T>> ThenAsync<T>(this Task<ResponseData<T>> taskData, Action<ResponseData<T>> action) {
        var data = await taskData;
        if (data.Success) {
            action.Invoke(data);
        }
        return data;
    }
    /// <summary>
    /// 如果<paramref name="taskData"/>.Success == <see langword="true"/> 则执行<paramref name="action"/>并返回执行结果，否则直接返回错误信息
    /// </summary>
    /// <typeparam name="Tin"></typeparam>
    /// <typeparam name="Tout"></typeparam>
    /// <param name="taskData"></param>
    /// <param name="action"></param>
    /// <returns></returns>
    public static async Task<ResponseData<Tout>> ThenAsync<Tin, Tout>(this Task<ResponseData<Tin>> taskData,
                                                                      Func<ResponseData<Tin>, ResponseData<Tout>> action) {
        var data = await taskData;
        if (data.Success) {
            return action.Invoke(data);
        }
        return ResponseData<Tout>.Error(data, data.Code);
    }
    /// <summary>
    /// 如果<paramref name="taskData"/>.Success == <see langword="false"/> 则执行<paramref name="action"/>并返回原始的<paramref name="taskData"/>，
    /// 否则直接返回<see langword="default"/> 
    /// </summary>
    /// <typeparam name="Tin"></typeparam>
    /// <typeparam name="Tout"></typeparam>
    /// <param name="taskData"></param>
    /// <param name="action"></param>
    /// <returns></returns>
    public static async Task<Tout?> ThenAsync<Tin, Tout>(this Task<ResponseData<Tin>> taskData,
                                                         Func<ResponseData<Tin>, Tout> action) {
        var data = await taskData;
        if (data.Success) {
            return action.Invoke(data);
        }
        return default;
    }
    /// <summary>
    /// 如果<paramref name="taskData"/>.Success == false 则执行<paramref name="action"/>并返回原始的<paramref name="taskData"/>，否则直接返回
    /// </summary>
    /// <param name="taskData"></param>
    /// <param name="action"></param>
    /// <returns></returns>
    public static async Task<ResponseData> CatchAsync(this Task<ResponseData> taskData, Action<ResponseData> action) {
        var data = await taskData;
        if (data.Success == false) {
            action.Invoke(data);
        }
        return data;
    }
    /// <summary>
    /// 返回一个成功的结果
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="data"></param>
    /// <returns></returns>
    public static ResponseData<T> GetSuccessResult<T>(this T data) where T : new() => ResponseData.Ok(data);
    /// <summary>
    /// 返回一个成功的结果
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="data"></param>
    /// <returns></returns>
    public static async Task<ResponseData<T>> GetSuccessResultAsync<T>(this Task<T> data) where T : new()
        => ResponseData.Ok(await data);
    /// <summary>
    /// 等待并检查是否成功
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="responseData"></param>
    /// <returns></returns>
    public static async Task<bool> IsSuccessAsync<T>(this Task<ResponseData<T>> responseData)
        => (await responseData).Success;
    /// <summary>
    /// 如果<paramref name="data"/>成功则执行<paramref name="action"/>并返回执行结果，否则直接返回错误信息
    /// </summary>
    /// <typeparam name="TOut"></typeparam>
    /// <typeparam name="TIn"></typeparam>
    /// <param name="data"></param>
    /// <param name="action"></param>
    /// <returns></returns>
    public static async Task<ResponseData<TOut>> IsSuccessAsync<TOut, TIn>(this Task<ResponseData<TIn>> data, Func<TIn, TOut> action) {
        var r = await data;
        if (r.Success) {
            return ResponseData<TOut>.Ok(action.Invoke(r.Data!));
        }
        return ResponseData<TOut>.Error(r);
    }
    /// <summary>
    /// 如果<paramref name="data"/>成功则执行<paramref name="action"/>并返回执行结果，否则直接返回错误信息
    /// </summary>
    /// <typeparam name="TIn"></typeparam>
    /// <param name="data"></param>
    /// <param name="action"></param>
    /// <returns></returns>
    public static async Task<ResponseData<TIn>> IsSuccessAsync<TIn>(this Task<ResponseData<TIn>> data, Action<TIn> action) {
        var r = await data;
        if (r.Success) {
            action.Invoke(r.Data!);
            return r;
        }
        return r;
    }
    /// <summary>
    /// 是否“空结构”，一般用在从JSON解析以后。
    /// </summary>
    /// <typeparam name="TOut"></typeparam>
    /// <param name="data"></param>
    /// <param name="result"></param>
    /// <returns>如果是“空结构”会返回<paramref name="result"/>，否则返回输入的数据<paramref name="data"/></returns>
    public static async Task<ResponseData<TOut>> IsEmptyAsync<TOut>(this Task<ResponseData<TOut>> data, ResponseData<TOut> result) {
        var r = await data;
        return r.IsEmpty ? result : r;
    }

}
